package com.example.sandbox.controller.order.abstractController;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.example.sandbox.dto.*;
import com.example.sandbox.dto.domain.PayOrder;
import com.example.sandbox.helper.BizException;
import com.example.sandbox.mapper.PayOrderMapper;
import com.example.sandbox.service.MchAppService;
import com.example.sandbox.service.PayOrderService;
import com.example.sandbox.util.StringKit;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Date;

/**
 * 创建支付订单抽象类 ApiController
 *
 * @Author Lierbao
 * @Date 2024/5/14 14:40
 */

@Slf4j
@Component
public class AbstractPayOrderController{

    @Autowired
    private MchAppService mchAppService;
    @Autowired
    private PayOrderService payOrderService;
    @Autowired
    private PayOrderMapper payOrderMapper;

    /**
     * 统一下单 ifCode
     **/
    public ApiRes unifiedOrderIfCode(String ifCode, GbpsdPayOrderRQ bizRQ) {
        // 响应数据
        UnifiedOrderRS bizRS = new UnifiedOrderRS();
        PayOrder payOrder = new PayOrder();
        try {
            String mchNo = bizRQ.getMchNo();
            String appId = bizRQ.getAppId();

            // 只有新订单模式，进行校验
//            if (payOrderService.count(
//                    PayOrder.gw().eq(PayOrder::getMchNo, mchNo).eq(PayOrder::getMchOrderNo, bizRQ.getMchOrderNo())) > 0) {
//                throw new BizException("Merchant order[" + bizRQ.getMchOrderNo() + "]Already exists");
//            }

            if (StringUtils.isNotEmpty(bizRQ.getNotifyUrl()) && !StringKit.isAvailableUrl(bizRQ.getNotifyUrl())) {
                throw new BizException(
                        "The asynchronous notification address protocol only supports HTTP:// 或 https:// !");
            }
            if (StringUtils.isNotEmpty(bizRQ.getReturnUrl()) && !StringKit.isAvailableUrl(bizRQ.getReturnUrl())) {
                throw new BizException(
                        "The asynchronous notification address protocol only supports HTTP:// 或 https:// !");
            }

            MchApp mchApp = mchAppService.getOne(MchApp.gw().eq(MchApp::getMchNo, mchNo));


            // 生成订单
            payOrder.setPayOrderId(bizRQ.getOrderId()); // 生成订单ID
            payOrder.setMchNo(mchApp.getMchNo()); // 商户号

            // 服务商号写死 调用的渠道
            payOrder.setIsvNo("zw0000000001"); // 渠道账号编码
            payOrder.setMchName(mchApp.getMchNo()); // 商户名称（简称）

            // 目前写死普通商户
            payOrder.setMchType(CS.INFO_TYPE_MCH); // 商户类型
            payOrder.setMchOrderNo(bizRQ.getMchOrderNo()); // 商户订单号
            payOrder.setAppId(mchApp.getAppId()); // 商户应用appId
            payOrder.setIfCode(ifCode); // 接口代码
            payOrder.setWayCode(bizRQ.getWayCode()); // 支付方式
            payOrder.setAmount(bizRQ.getAmount()); // 订单金额
            payOrder.setMchSingeFee(100L); // 手续费
            payOrder.setMchFeeRate(BigDecimal.valueOf(0)); // 订单金额
            payOrder.setMchFeeAmount(100L); // 订单金额

            // 新订单计算手续费并装配
//            commissionHelper.calculateAndAssemblerPayOrderCommission(mchPayPassage, payOrder);

            payOrder.setCurrency(bizRQ.getCurrency()); // 币种
            payOrder.setClientIp("0.0.0.1"); // 客户端IP
            payOrder.setSubject(bizRQ.getSubject()); // 商品标题
            payOrder.setBody(bizRQ.getBody()); // 商品描述信息
            // 之前的为了在payOrder对象需要传参。
            payOrder.setChannelUser(null); // 渠道用户标志
            payOrder.setExtParam(bizRQ.getExtParam()); // 商户扩展参数
            payOrder.setNotifyUrl(bizRQ.getNotifyUrl()); // 异步通知地址
            payOrder.setReturnUrl(bizRQ.getReturnUrl()); // 页面跳转地址
            payOrder.setAgentNoA("A0001");
            payOrder.setChannelExtra(bizRQ.getChannelExtra()); // 渠道扩展参数

            // 分账模式 目前分账模式固定为 DIVISION_MODE_AUTO
            payOrder.setDivisionMode(ObjectUtils.defaultIfNull(bizRQ.getDivisionMode(), PayOrder.DIVISION_MODE_AUTO));

            // 订单过期时间 单位： 秒
            Date nowDate = new Date();
            if (bizRQ.getExpiredTime() != null) {
                payOrder.setExpiredTime(DateUtil.offsetSecond(nowDate, bizRQ.getExpiredTime()));
            } else {
                payOrder.setExpiredTime(DateUtil.offsetHour(nowDate, 2)); // 订单过期时间 默认两个小时
            }

            // 订单入库 订单状态： 生成状态 此时没有和任何上游渠道产生交互。
            payOrder.setState(PayOrder.STATE_ING);
            log.info("下单入库参数 payOrder: {}", JSONObject.toJSONString(payOrder));
            payOrderMapper.insert(payOrder);

            // 调起上游支付接口
//            bizRS = (UnifiedOrderRS) paymentService.pay(bizRQ, payOrder, mchAppConfigContext);

            // 改为支付中
//            this.processChannelMsg(bizRS.getChannelRetMsg(), payOrder);

            return packageApiResByPayOrder(bizRS, payOrder);
        } catch (BizException e) {
            log.error("unifiedOrderIfCode BizException , 入参ifCode:[{}],UnifiedOrderRQ:[{}]", ifCode, JSONObject.toJSONString(bizRQ), e);
            return ApiRes.customFail(e.getMessage());
        } catch (Exception e) {
            log.error("unifiedOrderIfCode system error" , e);
            return ApiRes.customFail("system error");
        }
    }

    private void processChannelMsg(ChannelRetMsg channelRetMsg, PayOrder payOrder) {
        LambdaUpdateWrapper<PayOrder> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(PayOrder::getPayOrderId, payOrder.getPayOrderId())
                .set(PayOrder::getState, PayOrder.STATE_ING);
        payOrderService.update(lambdaUpdateWrapper);

    }

    /**
     * 统一封装订单数据
     **/
    private ApiRes packageApiResByPayOrder(UnifiedOrderRS bizRS, PayOrder payOrder) {

        // 返回接口数据
        bizRS.setPayOrderId(payOrder.getPayOrderId());
        bizRS.setOrderState(payOrder.getState());
        bizRS.setMchOrderNo(payOrder.getMchOrderNo());
        if (payOrder.getState() == PayOrder.STATE_FAIL) {
//            bizRS.setErrCode(bizRS.getChannelRetMsg() != null ? bizRS.getChannelRetMsg().getChannelErrCode() : null);
            bizRS.setErrMsg(bizRS.getChannelRetMsg() != null ? bizRS.getChannelRetMsg().getChannelErrMsg() : null);
        }
        return ApiRes.okWithSign(bizRS,
                mchAppService.getOneByMch(payOrder.getMchNo(), payOrder.getAppId()).getAppSecret());
    }



}
